﻿/*
 * ===================================================
 * Author     : <ClueeZhuo>
 * Create Time: <2018/5/13 3:22:15>
 * Description: <This is a Description of This File.>
 * ===================================================
 */



using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;

namespace helloworld.IOC
{
    /// <summary>
    /// Template Method
    /// </summary>
    public partial class MVCEngine
    {
        public virtual Request OnListenAndReceiveRequest(Uri uri) => new Request();
        public virtual Controller OnActivateControler(Request request) => (Controller)new object();
        public virtual View OnExecuteControler(Controller controller) => new View();
        public virtual void OnRenderView(View view) => new object();

        public EventHandler<ControllerActivationEventArgs> ControllerActivating;
        public EventHandler<ControllerActivationEventArgs> ControllerActivated;
        public EventHandler<ControllerExecutionEventArgs> ControllerExecuteing;
        public EventHandler<ControllerExecutionEventArgs> ControllerExecuted;
        public EventHandler<ViewRenderEventArgs> ViewRendering;
        public EventHandler<ViewRenderEventArgs> ViewRendered;

        /// <summary>
        /// 模板方法启动
        /// </summary>
        /// <param name="uri"></param>
        public void StartByTemplateMethod(Uri uri)
        {
            while (true)
            {
                Task.Run(() =>
                {
                    Request request = this.OnListenAndReceiveRequest(uri);
                    Controller controller = this.OnActivateControler(request);
                    View view = this.OnExecuteControler(controller);
                    this.OnRenderView(view);
                });
            }
        }
    }

    /// <summary>
    /// Factory Method
    /// </summary>
    public partial class MVCEngine
    {
        /// <summary>
        /// 工厂方法启动
        /// </summary>
        /// <param name="uri"></param>
        public void StartByFactoryMethod(Uri uri)
        {
            while (true)
            {
                Request request = this.GetListener().Listen(uri);
                Controller controller = this.GetControllerActivator().ActivateController(request);
                View view = this.GetControllerExecutor().ExecuteController(controller);
                this.GetViewRender().RendView(view);
            }
        }

        public virtual Listener GetListener() => new Listener();
        public virtual ControllerActivator GetControllerActivator() => new ControllerActivator();
        public virtual ControllerExecutor GetControllerExecutor() => new ControllerExecutor();
        public virtual ViewRender GetViewRender() => new ViewRender();
    }

    /// <summary>
    /// Abstract Method
    /// </summary>
    public partial class MVCEngine
    {
        public AbstractFactory AbstractFac { get; private set; }

        public MVCEngine(AbstractFactory abstractFac = null)
        {
            this.AbstractFac = abstractFac ?? new AbstractFactory();
        }

        public void StartByAbstractFactory(Uri uri)
        {
            while (true)
            {
                Request request = this.AbstractFac.GetListener().Listen(uri);
                Controller controller = this.AbstractFac.GetActivator().ActivateController(request);
                View view = this.AbstractFac.GetExecutor().ExecuteController(controller);
                this.GetViewRender().RendView(view);
            }
        }
    }

    /// <summary>
    /// 由外部容器提供服务对象
    /// </summary>
    public partial class MVCEngine
    {
        public Cat Cat { get; private set; }

        public MVCEngine(Cat cat)
        {
            this.Cat = cat;
        }

        public void Start(Uri uri)
        {

            while (true)
            {
                Request request = this.Cat.GetService<Listener>().Listen(uri);

                Task.Run(() =>
                {
                    Controller controller = this.Cat.GetService<ControllerActivator>().ActivateController(request);
                    View view = this.Cat.GetService<ControllerExecutor>().ExecuteController(controller);
                    this.Cat.GetService<ViewRender>().RendView(view);
                });
            }
        }
    }
}
